<template>
	<a-modal class="image-cropper-modal" v-model:open="visible" title="编辑图片" :footer="false" @cancel="closeModal">
		<div class="image-cropper">
			<vue-cropper
				ref="cropperRef"
				:img="imageUrl"
				:autoCrop="true"
				:fixedBox="false"
				:centerBox="true"
				:canMove="true"
				:canMoveBox="true"
				:info="true"
				outputType="png"
			/>
			<div style="margin-bottom: 16px" />
			<!-- 协同编辑操作 -->
			<div>
				<a-space class="image-edit-actions" v-if="isTeamSpace">
					<a-button v-if="editingUser" disabled>{{ editingUser.userName }} 正在编辑</a-button>
					<a-button v-if="canEnterEdit" type="primary" ghost @click="enterEdit">进入编辑</a-button>
					<a-button v-if="canExitEdit" danger ghost @click="exitEdit">退出编辑</a-button>
				</a-space>
			</div>
			<!-- 图片操作 -->
			<div class="image-cropper-actions">
				<a-space>
					<a-button @click="rotateLeft" :disabled="!canEdit">向左旋转</a-button>
					<a-button @click="rotateRight" :disabled="!canEdit">向右旋转</a-button>
					<a-button @click="changeScale(1)" :disabled="!canEdit">放大</a-button>
					<a-button @click="changeScale(-1)" :disabled="!canEdit">缩小</a-button>
					<a-button type="primary" :loading="loading" @click="handleConfirm" :disabled="!canEdit">确认</a-button>
				</a-space>
			</div>
		</div>
	</a-modal>
</template>

<script setup lang="ts">
import { uploadPictureUsingPost } from '@/api/pictureController'
import { PICTURE_EDIT_ACTION_ENUM, PICTURE_EDIT_MESSAGE_TYPE_ENUM } from '@/constants/picture'
import { SPACE_TYPE_ENUM } from '@/constants/space'
import { useLoginUserStore } from '@/stores/useLoginUserStore'
import PictureEditWebSocket from '@/utils/pictureEditWebSocket'
import { message } from 'ant-design-vue'
import { computed, onUnmounted, ref, watchEffect } from 'vue'

interface Props {
	imageUrl?: string
	picture?: API.PictureVO
	spaceId?: any
	space?: API.SpaceVO
	onSuccess?: (newPicture: API.PictureVO) => void
}

const props = defineProps<Props>()

// 是否为团队空间
const isTeamSpace = computed(() => {
	return props.space?.spaceType === SPACE_TYPE_ENUM.TEAM
})

// 编辑器组件的引用
const cropperRef = ref()

// 向左旋转
const rotateLeft = () => {
	cropperRef.value.rotateLeft()
	editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT)
}

// 向右旋转
const rotateRight = () => {
	cropperRef.value.rotateRight()
	editAction(PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT)
}

// 缩放
const changeScale = (num: number) => {
	cropperRef.value.changeScale(num)
	if (num > 0) {
		editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_IN)
	} else {
		editAction(PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT)
	}
}

const loading = ref(false)
// 图片上传操作
const handleUpload = async ({ file }: any) => {
	loading.value = true
	try {
		// 调用上传接口
		const params: API.PictureUploadRequest = props.picture ? { id: props.picture.id } : {}
		params.spaceId = props.spaceId
		const res: any = await uploadPictureUsingPost(params, {}, file)
		if (res.data.code === 0 && res.data.data) {
			message.success('图片上传成功')
			// 将上传图片成功的信息传递给父组件
			props.onSuccess?.(res.data.data)
		} else {
			message.error('图片上传失败，' + res.data.message)
		}
	} catch (error: any) {
		console.error('图片上传失败', error)
		message.error('图片上传失败，' + error.message)
	}
	loading.value = false
}

// 确认裁切
const handleConfirm = () => {
	cropperRef.value.getCropBlob((blob: Blob) => {
		// blob 为已裁切的文件
		const fileName = (props.picture?.name || 'image') + '.png'
		const file = new File([blob], fileName, { type: blob.type })
		// 上传图片
		handleUpload({ file })
	})
}

const visible = ref<boolean>(false)

const openModal = () => {
	visible.value = true
}

const closeModal = () => {
	visible.value = false
	if (websocket) {
		websocket.disconnect()
	}
	editingUser.value = undefined
}

// 暴露函数给父组件
defineExpose({
	openModal,
	closeModal,
})

// ------------- 实时编辑 -----------------
const loginUserStore = useLoginUserStore()
const loginUser = loginUserStore.loginUser

// 正在编辑的用户
const editingUser = ref<API.UserVO>()

// 当前用户是否可进入编辑
const canEnterEdit = computed(() => {
	return !editingUser.value
})

// 当前编辑的用户是本人，可退出编辑
const canExitEdit = computed(() => {
	return editingUser.value?.id === loginUser?.id
})

// 可以点击编辑图片的操作按钮
const canEdit = computed(() => {
	// 如果不是团队空间，默认就可以编辑
	if (!isTeamSpace.value) {
		return true
	}
	// 团队空间，只有编辑者才能协同编辑
	return editingUser.value?.id === loginUser?.id
})

// ------------- 编写 WebSocket 逻辑 -------------------
let websocket: PictureEditWebSocket | null

// 初始化 websocket 连接
const initWebSocket = () => {
	const pictureId = props.picture?.id
	if (!pictureId || !visible.value) {
		return
	}
	// 防止之前的连接未释放
	if (websocket) {
		websocket.disconnect()
	}
	// 创建 websocket 实例
	websocket = new PictureEditWebSocket(pictureId)
	// 建立连接
	websocket.connect()

	// 监听一系列的事件
	websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.INFO, (msg) => {
		message.info(msg.message)
	})

	websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ERROR, (msg) => {
		message.error(msg.message)
	})

	websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT, (msg) => {
		message.info(msg.message)
		editingUser.value = msg.user
	})

	websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION, (msg) => {
		message.info(msg.message)
		// 根据收集到的编辑操作类型执行相应的操作
		switch (msg.editAction) {
			case PICTURE_EDIT_ACTION_ENUM.ROTATE_LEFT:
				rotateLeft()
				break
			case PICTURE_EDIT_ACTION_ENUM.ROTATE_RIGHT:
				rotateRight()
				break
			case PICTURE_EDIT_ACTION_ENUM.ZOOM_IN:
				changeScale(1)
				break
			case PICTURE_EDIT_ACTION_ENUM.ZOOM_OUT:
				changeScale(-1)
				break
		}
	})

	websocket.on(PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT, (msg) => {
		message.info(msg.message)
		editingUser.value = undefined
	})
}

// 监听属性和 visible 变化，初始化 Websocket 链接
watchEffect(() => {
	// 只有团队空间，才初始化 WebSocket 连接
	if (isTeamSpace.value) {
		initWebSocket()
	}
})

// 组件销毁时，关闭 websocket 连接
onUnmounted(() => {
	if (websocket) {
		websocket.disconnect()
	}
	editingUser.value = undefined
})

// 进入编辑
const enterEdit = () => {
	if (websocket) {
		// 发送进入编辑状态的请求
		websocket.sendMessage({
			type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.ENTER_EDIT,
		})
	}
}

// 退出编辑
const exitEdit = () => {
	if (websocket) {
		// 发送退出编辑状态的请求
		websocket.sendMessage({
			type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EXIT_EDIT,
		})
	}
	editingUser.value = undefined
}

// 编辑图片操作
const editAction = (action: string) => {
	if (websocket) {
		// 发送编辑操作的请求
		websocket.sendMessage({
			type: PICTURE_EDIT_MESSAGE_TYPE_ENUM.EDIT_ACTION,
			editAction: action,
		})
	}
}
</script>

<style scoped lang="scss">
.image-cropper-modal {
	.image-edit-actions {
		margin-bottom: 16px;
	}
	.image-cropper {
		text-align: center;
		.vue-cropper {
			height: 400px;
		}
	}
}
</style>
